package com.vae.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.vae.auth.domain.XcMenu;
import com.vae.auth.mapper.XcMenuMapper;
import org.springframework.context.ApplicationContext;
import com.vae.auth.dto.AuthParamsDto;
import com.vae.auth.dto.XcUserExt;
import com.vae.auth.mapper.XcUserMapper;
import com.vae.auth.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class UserServiceImpl implements UserDetailsService {

    @Autowired
    XcUserMapper xcUserMapper;

    @Autowired
    //注入spring的容器
    ApplicationContext applicationContext;

    @Autowired
    XcMenuMapper xcMenuMapper;

    @Override
    //认证，这个方法会接收一个username用户名。由于这个username携带的信息被我们扩展过，所以username其实就是jwt令牌携带的用户信息
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //下面是统一认证入口----------------------------------------------------
        AuthParamsDto authParamsDto = null;
        try {
            authParamsDto = JSON.parseObject(username, AuthParamsDto.class);
        } catch (Exception e) {
            throw new RuntimeException("请求认证的参数不符合要求");
        }

        //获取是什么认证类型，有账号密码(password)、验证码(sms)、微信扫码(wx)
        String authType = authParamsDto.getAuthType();

        //根据认证类型，取出我们写的AuthService接口的对应实现类bean
        String beanName = authType+"_authservice";
        AuthService authService = applicationContext.getBean(beanName, AuthService.class);
        //调用统一认证的execute方法
        XcUserExt xcUserExt = authService.execute(authParamsDto);
        //上面是统一认证入口----------------------------------------------------

        UserDetails userPrincipal = getUserPrincipal(xcUserExt);
        return userPrincipal;
    }

    /**
     *  查询用户信息
     */
    public UserDetails getUserPrincipal(XcUserExt xcUserExt){

        String[] authorities = new String[0]; //初始化数组

        //查询用户拥有的权限，然后交给security框架
        List<XcMenu> xcMenuList = xcMenuMapper.selectPermissionByUserId(xcUserExt.getId());
        if (xcMenuList.size()>0) {
            List<String> permission = new ArrayList<>();
            xcMenuList.forEach(m->{
                //把xcMenuList集合的code值，放入permission集合
                permission.add(m.getCode());
            });
            //集合转数组
            authorities = permission.toArray(new String[0]);
        }

        //如果存在就拿到这个用户的密码，把密码交给security框架提供的User类，然后return，security框架就会去自动校验密码了。由于现在是认证，权限后面才做，所以authorities先随便写一个todo字符串
        String password = xcUserExt.getPassword();
        //扩展jwt携带的用户信息。思路: 把用户相关的信息查询出来，然后转成字符串json之后，就能放入User.withUsername()
        String userJson = JSON.toJSONString(xcUserExt);
        UserDetails userDetails = User.withUsername(userJson).password(password).authorities(authorities).build();
        return userDetails;
    }

}